package dao.jpa.controledao;

import Exception.InfraestruturaException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JPAUtil {

    private static EntityManagerFactory emf = null;
    private static final ThreadLocal<EntityManager> threadEntityManager = new ThreadLocal<EntityManager>();
    private static final ThreadLocal<EntityTransaction> threadTransaction = new ThreadLocal<EntityTransaction>();

    public static void startUp() {
        emf = Persistence.createEntityManagerFactory("aspectj");
    }

    public static EntityManager getEntityManager() {

        EntityManager s = threadEntityManager.get();
        try {
            if (s == null) {
                s = emf.createEntityManager();
                threadEntityManager.set(s);
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        }
        return s;
    }

    public static void closeEntityManager() {
        EntityManager s = threadEntityManager.get();
        threadEntityManager.set(null);
        if (s != null && s.isOpen()) {
            s.close();
//            System.out.println("Fechou a sessão para=" + Thread.currentThread().getName());
        }

        EntityTransaction tx = threadTransaction.get();
        if (tx != null && tx.isActive()) {
            rollbackTransaction();
            throw new RuntimeException("EntityManager sendo fechado " +
                    "com transação ativa.");
        }
    }

    public static void beginTransaction() {
        EntityTransaction tx = threadTransaction.get();
        if (tx == null) {
            tx = getEntityManager().getTransaction();
            tx.begin();
            threadTransaction.set(tx);
//            System.out.println("Criou transacao para=" + Thread.currentThread().getName());
        }
//            else {
//            System.out.println("Nao criou transacao para=" + Thread.currentThread().getName());
//
//        }
    }

    public static boolean isTransacaoAtiva() {
        EntityTransaction tx = threadTransaction.get();
        return (tx != null && tx.isActive());
    }

    public static void commitTransaction() {
        EntityTransaction tx = threadTransaction.get();
        if (tx != null && tx.isActive()) {
            tx.commit();
//            System.out.println("Comitou transacao para=" + Thread.currentThread().getName());
        }
        threadTransaction.set(null);
    }

    public static void rollbackTransaction() {
        EntityTransaction tx = threadTransaction.get();
        try {
            threadTransaction.set(null);
            if (tx != null && tx.isActive()) {
                tx.rollback();
            }
        } catch (RuntimeException ex) {
            throw new InfraestruturaException(ex);
        } finally {
            closeEntityManager();
        }
    }
}
